package com.yutong.redis.core;

import com.yutong.redis.fallback.DefaultIdFallback;
import com.yutong.redis.fallback.IdFallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author hao
 */
@Component
public class RedisIdTemplate {
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisTemplate.class);

    @Autowired
    private RedisIdWorker redisIdWorker;

    @Autowired
    private DefaultIdFallback defaultIdFallback;

    @Value("${spring.application.code:1001}")
    private String appCode;

    /**
     * 按规则生成ID
     *
     * @param key        redis key名称，同时作为ID前缀（若配置了需要前缀）
     * @param digits     redis id位数，id不足位数则在前面补0，默认0
     * @param increment  redis id增长步长，默认1
     * @param initial    redis id初始化值，默认从0开始
     * @param idFallback redis不可用时，服务降级的ID生成策略
     * @return ID
     */
    public String next(String key, int digits, Integer increment, Long initial, IdFallback idFallback) {
        StringBuffer seq = new StringBuffer();
        if (StringUtils.isEmpty(key)) {
            key = appCode;
        }
        seq.append(key);
        try {
            DateTimeFormatter dateTimeFormatter = SimpleDateFormatter.FORMATTER_DAY;
            String dateStr = dateTimeFormatter.format(LocalDateTime.now());
            long ttl = 86400;
            Long id = redisIdWorker.incr(getRedisKeyName(key, dateStr), increment, initial, ttl);
            String formatRedisId = digits > 0 ? String.format("%0" + digits + "d", id) : String.valueOf(id);
            return seq.append(dateStr).append(formatRedisId).toString();
        } catch (Exception ex) {
            //为了容错和服务降级, 当Redis不能提供服务或其他异常错误导致生成失败时
            LOGGER.error("通过Redis生成唯一ID失败，采用服务降级策略生成", ex);
        }
        //没有配置ID服务降级策略，则使用默认策略
        idFallback = (idFallback == null) ? defaultIdFallback : idFallback;
        return seq.append(idFallback.nextId()).toString();
    }

    public String next(String key) {
        return next(key, 6, 1, 0l, defaultIdFallback);
    }


    public String next() {
        return next(null);
    }

    public String getRedisKeyName(String key, String dateStr) {
        StringBuffer redisKey = new StringBuffer().append(key);
        redisKey.append("_").append(dateStr);
        return redisKey.toString();
    }

}
